package ebedynky.controllers;

import ebedynky.beans.*;
import ebedynky.editors.EditorFactory;
import ebedynky.services.*;
import java.sql.Timestamp;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.validation.*;
import org.springframework.stereotype.Controller;
import org.springframework.ui.*;
import org.springframework.validation.*;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;

/**
 * @author Ondrej David (davidon1)
 */
@Controller
public class BoxOrderController {

    /**
     * Initialises the data binder.
     * @param binder the data binder to be initialised
     */
    @InitBinder
    protected void initBinder(WebDataBinder binder) {
        try {
            //        binder.setValidator(new BoxOrderValidator());
            binder.registerCustomEditor(Customer.class, EditorFactory.getCustomerIDEditor());
            binder.registerCustomEditor(Timestamp.class, EditorFactory.getTimestampFromStringEditor());
            binder.registerCustomEditor(BoxOrder.class, EditorFactory.getBoxOrderIDEditor());
            binder.registerCustomEditor(Set.class, "orderitems", EditorFactory.getOrderItemIDtoSetEditor());
            binder.registerCustomEditor(Set.class, "boxes", EditorFactory.getBoxIDtoSetEditor());
        } catch (Exception ex) {
            Logger.getLogger(BoxOrderController.class.getName()).log(Level.SEVERE, "Binder failed at BoxOrderController", ex);
        }
    }

    /**
     * Fetches the index page when requested.
     * @param model data holder for this view
     * @return string representing page location
     */
    @RequestMapping(value = "/order", method = RequestMethod.GET)
    public String getIndex(Model model) {
        return "order/index";
    }

    /**
     * Fetches the BoxOrder adding page when requested.
     * @param model data holder for this view
     * @return string representing page location
     */
    @RequestMapping(value = "/orderAdd", method = RequestMethod.GET)
    public String getCreateForm(Model model) {
        model.addAttribute(new BoxOrder());
        return "order/createForm";
    }

    /**
     * Extracts the BoxOrder data from the form,
     * validates them and stores them into the db.
     * @param boxOrder data from the form
     * @param result data binding result
     * @return string representing next (success/failure) page location
     */
    @RequestMapping(value = "/orderAdd", method = RequestMethod.POST)
    public String create(@Valid BoxOrder boxOrder, BindingResult result) {
        if (result.hasErrors()) {
            return "order/createForm";
        }
        BoxOrderService bos = new BoxOrderService();
        bos.addBoxOrder(boxOrder);
        return "order/index";
    }

    /**
     * Fetches the BoxOrder delete page when requested.
     * @param model data holder for this view
     * @return string representing page location
     */
    @RequestMapping(value = "/orderDel", method = RequestMethod.GET)
    public String getDeleteForm(Model model) {
        model.addAttribute(new BoxOrder());
        return "order/deleteForm";
    }

    /**
     * Deletes the corresponding BoxOrder data from the db.
     * @param boxOrder data from the form
     * @param result data binding result
     * @return string representing next (success/failure) page location
     */
    @RequestMapping(value = "/orderDel", method = RequestMethod.POST)
    public String delete(@Valid BoxOrder boxOrder, BindingResult result) {
        if (result.hasErrors()) {
            return "order/deleteForm";
        }
        BoxOrderService bos = new BoxOrderService();
        bos.deleteBoxOrder(boxOrder.getBoxOrderID());
        return "order/index";
    }

    /**
     * Fetches the BoxOrder select page when requested.
     * @param model data holder for this view
     * @return string representing page location
     */
    @RequestMapping(value = "/orderSel", method = RequestMethod.GET)
    public String getSelectForm(Model model) {
        model.addAttribute(new BoxOrder());
        return "order/selectForm";
    }

    /**
     * Selects the corresponding BoxOrder data from the db.
     * @param boxOrder data from the form
     * @param result data binding result
     * @return string representing next (success/failure) page location
     */
    @RequestMapping(value = "/orderSel", method = RequestMethod.POST)
    public String select(@Valid BoxOrder boxOrder, BindingResult result) {
        if (result.hasErrors()) {
            return "order/selectForm";
        }
        return "redirect:/orderMod/" + String.valueOf(boxOrder.getBoxOrderID());
    }

    /**
     * Fetches the BoxOrder modify page when requested.
     * @param id of the BoxOrder to modify
     * @param model data holder for this view
     * @return string representing page location
     */
    @RequestMapping(value = "/orderMod/{id}", method = RequestMethod.GET)
    public String getModifyForm(@PathVariable Integer id, Model model) {
        try {
            BoxOrderService os = new BoxOrderService();
            model.addAttribute(os.getBoxOrderByID(id.intValue()));
        } catch (Exception ex) {
            Logger.getLogger(BoxOrderController.class.getName()).log(Level.SEVERE, null, ex);
        }
        return "order/modifyForm";
    }

    /**
     * Modifies the corresponding BoxOrder data in the db.
     * @param boxOrder data from the form
     * @param result data binding result
     * @return string representing next (success/failure) page location
     */
    @RequestMapping(value = "/orderMod", method = RequestMethod.POST)
    public String modify(@Valid BoxOrder boxOrder, BindingResult result) {
        if (result.hasErrors()) {
            return "order/modifyForm";
        }
        BoxOrderService bos = new BoxOrderService();
        bos.updateBoxOrder(boxOrder);
        return "order/index";
    }

    /**
     * Adds a BoxOrder map extracted from the db as an attribute to the model.
     * @return Map<Integer, String> map of BoxOrderIDs and names
     */
    @ModelAttribute("boxOrderList")
    protected Map<Integer, String> boxOrderData() {
        Map<Integer, String> oMap = new ConcurrentHashMap<Integer, String>();
        BoxOrderService os = new BoxOrderService();
        List<BoxOrder> list = os.getAllBoxOrders();
        Iterator<BoxOrder> it = list.iterator();
        BoxOrder o;
        while (it.hasNext()) {
            o = it.next();
            oMap.put(o.getBoxOrderID(), o.toString());
        }
        return oMap;
    }

    /**
     * Adds a Customer map extracted from the db as an attribute to the model.
     * @return Map<Integer, String> map of CustomerIDs and names
     */
    @ModelAttribute("customerList")
    protected Map<Integer, String> customerData() {
        Map<Integer, String> cMap = new ConcurrentHashMap<Integer, String>();
        CustomerService cs = new CustomerService();
        List<Customer> list = cs.getAllCustomers();
        Iterator<Customer> it = list.iterator();
        Customer c;
        while (it.hasNext()) {
            c = it.next();
            cMap.put(c.getUserID(), c.toString());
        }
        return cMap;
    }

    /**
     * Adds a OrderItem map extracted from the db as an attribute to the model.
     * @return Map<Integer, String> map of OrderItemIDs and names
     */
    @ModelAttribute("orderItemList")
    protected Map<Integer, String> orderItemData() {
        Map<Integer, String> oiMap = new ConcurrentHashMap<Integer, String>();
        OrderItemService ois = new OrderItemService();
        List<OrderItem> list = ois.getAllOrderItems();
        Iterator<OrderItem> it = list.iterator();
        OrderItem oi;
        while (it.hasNext()) {
            oi = it.next();
            oiMap.put(oi.getOrderItemID(), oi.toString());
        }
        return oiMap;
    }

    /**
     * Adds a box map extracted from the db as an attribute to the model.
     * @return Map<Integer, String> map of boxIDs and names
     */
    @ModelAttribute("boxList")
    protected Map<Integer, String> boxData() {
        Map<Integer, String> bMap = new ConcurrentHashMap<Integer, String>();
        BoxService bs = new BoxService();
        List<Box> list = bs.getAllBoxes();
        Iterator<Box> it = list.iterator();
        Box b;
        while (it.hasNext()) {
            b = it.next();
            bMap.put(b.getBoxID(), b.toString());
        }
        return bMap;
    }
}
